﻿// 
// Copyright (c) 2013 Jason Bell
// 
// Permission is hereby granted, free of charge, to any person obtaining a 
// copy of this software and associated documentation files (the "Software"), 
// to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, 
// and/or sell copies of the Software, and to permit persons to whom the 
// Software is furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included 
// in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
// DEALINGS IN THE SOFTWARE.
// 

using System;
using System.Drawing;

using Gharen.GLCore;

namespace ExampleDraw
{
    public class Texture
        : IDisposable
    {
        public int Reference { get; private set; }

        public int Width { get; private set; }
        public int Height { get; private set; }

        GLES30 gl;

        public Texture(GLES30 gl, string filename)
        {
            this.gl = gl;

            this.Reference = gl.GenTexture();

            this.Bind();

            var bmp = new Bitmap(filename);

            this.Width = bmp.Width;
            this.Height = bmp.Height;

            var data = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height),
                System.Drawing.Imaging.ImageLockMode.ReadOnly,
                System.Drawing.Imaging.PixelFormat.Format32bppArgb);

            /* OpenGL ES doesn't provide the BGRA format, so we have to swap the 
             * red and blue components ourselves. */
            unsafe
            {
                byte * colorPtr = (byte *)data.Scan0.ToPointer();
                for (int i = 0; i < (bmp.Width * bmp.Height * 4); i+=4)
                {
                    byte b = colorPtr[i];
                    byte g = colorPtr[i + 1];
                    byte r = colorPtr[i + 2];
                    byte a = colorPtr[i + 3];
                    colorPtr[i] = r;
                    colorPtr[i + 1] = g;
                    colorPtr[i + 2] = b;
                    colorPtr[i + 3] = a;
                }
            }

            gl.TexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, data.Width, data.Height, 0,
                gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, data.Scan0); // was GL_BGRA

            bmp.UnlockBits(data);

            bmp.Dispose();

            gl.TexParameter(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR);
            gl.TexParameter(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR);
        }

        public void Dispose()
        {
            if (this.Reference != 0)
            {
                gl.DeleteTexture(this.Reference);
                this.Reference = 0;
            }
        }

        public void Bind()
        {
            gl.ActiveTexture(gl.GL_TEXTURE0);
            gl.BindTexture(gl.GL_TEXTURE_2D, this.Reference);
        }
    }
}
